package net.love5z.web.controller;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.love5z.web.common.cache.GaeCacheService;
import net.love5z.web.service.ShortUrlService;
import net.love5z.web.service.bo.PaginationShortUrlListBo;
import net.love5z.web.service.bo.ShortUrlBo;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class ShortUrlController {
    public static final Logger logger = Logger.getLogger("SHORTURL");

    @Autowired
    private ShortUrlService    shortUrlService;

    @Autowired
    private GaeCacheService    cacheService;

    @RequestMapping(value = "/s/", method = RequestMethod.GET)
    public String index(ModelMap map, HttpServletRequest request, HttpServletResponse response) {
        return "short_url/index.vm";
    }

    @RequestMapping(value = "/s/", method = RequestMethod.POST)
    public String shorten(ModelMap map, HttpServletRequest request, HttpServletResponse response) {
        String longUrl = request.getParameter("longurl");
        if (!isValidLongUrl(longUrl)) {
            map.put("error", "Invalid long url!");
            return "short_url/index.vm";
        } else {
            if (isSameDomainUrl(longUrl, request.getServerName())) {
                map.put("error", "Invalid long url!");
            } else {
                ShortUrlBo su = shortUrlService.getByLongUrl(longUrl);
                if (su != null) {
                    map.addAttribute("opCode", su.getOpCode());
                } else {
                    // 插入
                    String opCode = shortUrlService.insertLongUrl(longUrl);
                    map.addAttribute("opCode", opCode);
                }
            }
        }
        return "short_url/index.vm";
    }

    @RequestMapping(value = "/sl/", method = RequestMethod.GET)
    public String list(ModelMap map, HttpServletRequest request, HttpServletResponse response) {

        return listPage(1, map, request, response);
    }

    @RequestMapping(value = "/sl/{pageNo}/", method = RequestMethod.GET)
    public String listPage(@PathVariable("pageNo")
    int pageNo, ModelMap map, HttpServletRequest request, HttpServletResponse response) {
        logger.info(request.getServletPath());
        logger.info(request.getRequestURL());

        int pageCount = 20;

        PaginationShortUrlListBo paginationShortUrlListBo = shortUrlService.listPage(pageNo,
            pageCount);

        map.addAttribute("sUrlList", paginationShortUrlListBo.getList());
        map.addAttribute("pageNo", pageNo);
        map.addAttribute("totalPages", paginationShortUrlListBo.getTotalPages());

        return "short_url/list.vm";
    }

    @RequestMapping(value = "/s/{opCode}", method = { RequestMethod.GET, RequestMethod.HEAD })
    public void redirect(@PathVariable("opCode")
    String opCode, ModelMap map, HttpServletRequest request, HttpServletResponse response) {
        logger.info(request.getRequestURL().toString() + "-" + request.getHeader("REFERER"));

        String cacheKey = "love5z.shorturl.ShortUrlBo." + opCode;

        ShortUrlBo su = (ShortUrlBo) cacheService.get(cacheKey);

        if (su == null) {
            su = shortUrlService.getByOpCode(opCode);

            if (su != null) {
                cacheService.put(cacheKey, su, 24 * 60 * 60);
            }
        }

        if (su != null) {
            shortUrlService.upDataAccessTimesById(su.getId());
            response.setStatus(301);
            response.setHeader("Location", response.encodeRedirectURL(su.getLongUrl()));
            response.setHeader("Content-Type", "text/html; charset=UTF-8");
        } else {
            try {
                response.sendError(404);
            } catch (IOException e) {
            }
        }

    }

    private boolean isValidLongUrl(String longurl) {
        try {
            @SuppressWarnings("unused")
            URL url = new URL(longurl);
        } catch (MalformedURLException e) {
            return false;
        }

        return true;
    }

    private boolean isSameDomainUrl(String longurl, String host) {
        try {
            URL url = new URL(longurl);
            if (StringUtils.equalsIgnoreCase(url.getHost(), host)) {
                return true;
            }
        } catch (MalformedURLException e) {
            return true;
        }

        return false;
    }

}
